#ifndef DECLARATIONS_H
#define DECLARATIONS_H

#include <string>
#include <map>
#include <deque>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <stack>

using namespace std;

enum type_name { bool_type, string_type, double_type, pointer_type, int_type, error_type, void_type };

struct values_struct
{		
	type_name type;
	char name[31];
	union 
	{
		int decimal_value;
		double double_value;
		bool bool_value;
		char string_value[256];
	} value;
};

struct function_struct
{
	type_name type;
	vector<string> param_names;
	vector<type_name> param_types;
};	

typedef deque<map<string, values_struct> > symbol_table;
typedef map<string, function_struct> function_table;

values_struct* findKey(symbol_table& table, string key);
bool keyExistsInCurrScope(symbol_table& table, string key);
void addSymbol(symbol_table& table, string key, values_struct value);
void pushScope(symbol_table& table);
void popScope(symbol_table& table);
char* getTypeName(type_name type);

void validateVariableDeclaration(values_struct& type, values_struct& id, values_struct& rule, symbol_table& table);
void validateLeftValue(values_struct& a, values_struct& rule, symbol_table& table);
void validateAssignmentOp(values_struct& a, values_struct& b, values_struct& rule);
void validateArithOp(values_struct& a, values_struct& b, values_struct& rule);
void validateModuleOp(values_struct& a, values_struct& b, values_struct& rule);
void validateMinusOp(values_struct& a, values_struct& rule);
void validateRelationEqualOp(values_struct& a, values_struct& b, values_struct& rule);
void validateBoolOp(values_struct& a, values_struct& b, values_struct& rule);
void validateBoolOp(values_struct& a, values_struct& rule);
void validatePrintArg(values_struct& a, values_struct& rule);
void validateBoolCond(values_struct& condition);

void addFunction(map<string, function_struct>& functions, string name, type_name type);
bool functionExists(map<string, function_struct>& functions);
bool functionExists(function_table& functions, string name);
void validateFunctionDeclaration(symbol_table& table, function_table& functions, values_struct& type, values_struct& id, values_struct& rule);
void validateFunctionParams(function_table& functions, string functionName, values_struct& variables);
bool vectorContains(vector<string> vec, string paramName);
void validateBreak(stack<string>& breakLabel);
void validateReturnVoid(function_table& functions, string functionName);
void validateReturnType(function_table& functions, string functionName, type_name returnType);
void validateFunctionCallName(function_table& functions, string functionName, string currFunctionName);
void validateFunctionCallParams(function_table& functions, vector<type_name>& call_params, string functionName);
void addCallParamType(vector<type_name>& param_types, type_name type);
#endif


